home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2002 November / CD 1 / APC0211D1.ISO / workshop / prog / files / ActivePerl-5.6.1.633-MSWin32.msi / _d21206610d4ed1f33a82b9f45610d01d < prev    next >
Encoding:
Text File  |  2002-05-01  |  9.9 KB  |  395 lines

  1. #
  2. # $Id: Response.pm,v 1.36 2001/11/15 06:42:40 gisle Exp $
  3.  
  4. package HTTP::Response;
  5.  
  6.  
  7. =head1 NAME
  8.  
  9. HTTP::Response - Class encapsulating HTTP Responses
  10.  
  11. =head1 SYNOPSIS
  12.  
  13.  require HTTP::Response;
  14.  
  15. =head1 DESCRIPTION
  16.  
  17. The C<HTTP::Response> class encapsulates HTTP style responses.  A
  18. response consists of a response line, some headers, and (potentially
  19. empty) content. Note that the LWP library also uses HTTP style
  20. responses for non-HTTP protocol schemes.
  21.  
  22. Instances of this class are usually created and returned by the
  23. C<request()> method of an C<LWP::UserAgent> object:
  24.  
  25.  #...
  26.  $response = $ua->request($request)
  27.  if ($response->is_success) {
  28.      print $response->content;
  29.  } else {
  30.      print $response->error_as_HTML;
  31.  }
  32.  
  33. C<HTTP::Response> is a subclass of C<HTTP::Message> and therefore
  34. inherits its methods.  The inherited methods most often used are header(),
  35. push_header(), remove_header(), and content().
  36. The header convenience methods are also available.  See
  37. L<HTTP::Message> for details.
  38.  
  39. The following additional methods are available:
  40.  
  41. =over 4
  42.  
  43. =cut
  44.  
  45.  
  46. require HTTP::Message;
  47. @ISA = qw(HTTP::Message);
  48. $VERSION = sprintf("%d.%02d", q$Revision: 1.36 $ =~ /(\d+)\.(\d+)/);
  49.  
  50. use HTTP::Status ();
  51. use strict;
  52.  
  53.  
  54. =item $r = HTTP::Response->new($rc, [$msg, [$header, [$content]]])
  55.  
  56. Constructs a new C<HTTP::Response> object describing a response with
  57. response code C<$rc> and optional message C<$msg>.  The message is a
  58. short human readable single line string that explains the response
  59. code.
  60.  
  61. =cut
  62.  
  63. sub new
  64. {
  65.     my($class, $rc, $msg, $header, $content) = @_;
  66.     my $self = $class->SUPER::new($header, $content);
  67.     $self->code($rc);
  68.     $self->message($msg);
  69.     $self;
  70. }
  71.  
  72.  
  73. sub clone
  74. {
  75.     my $self = shift;
  76.     my $clone = bless $self->SUPER::clone, ref($self);
  77.     $clone->code($self->code);
  78.     $clone->message($self->message);
  79.     $clone->request($self->request->clone) if $self->request;
  80.     # we don't clone previous
  81.     $clone;
  82. }
  83.  
  84. =item $r->code([$code])
  85.  
  86. =item $r->message([$message])
  87.  
  88. =item $r->request([$request])
  89.  
  90. =item $r->previous([$previousResponse])
  91.  
  92. These methods provide public access to the object attributes.  The
  93. first two contain respectively the response code and the message
  94. of the response.
  95.  
  96. The request attribute is a reference the request that caused this
  97. response.  It does not have to be the same request as passed to the
  98. $ua->request() method, because there might have been redirects and
  99. authorization retries in between.
  100.  
  101. The previous attribute is used to link together chains of responses.
  102. You get chains of responses if the first response is redirect or
  103. unauthorized.
  104.  
  105. =cut
  106.  
  107. sub code      { shift->_elem('_rc',      @_); }
  108. sub message   { shift->_elem('_msg',     @_); }
  109. sub previous  { shift->_elem('_previous',@_); }
  110. sub request   { shift->_elem('_request', @_); }
  111.  
  112. =item $r->status_line
  113.  
  114. Returns the string "E<lt>code> E<lt>message>".  If the message attribute
  115. is not set then the official name of E<lt>code> (see L<HTTP::Status>)
  116. is substituted.
  117.  
  118. =cut
  119.  
  120. sub status_line
  121. {
  122.     my $self = shift;
  123.     my $code = $self->{'_rc'}  || "000";
  124.     my $mess = $self->{'_msg'} || HTTP::Status::status_message($code) || "?";
  125.     return "$code $mess";
  126. }
  127.  
  128. =item $r->base
  129.  
  130. Returns the base URI for this response.  The return value will be a
  131. reference to a URI object.
  132.  
  133. The base URI is obtained from one the following sources (in priority
  134. order):
  135.  
  136. =over 4
  137.  
  138. =item 1.
  139.  
  140. Embedded in the document content, for instance <BASE HREF="...">
  141. in HTML documents.
  142.  
  143. =item 2.
  144.  
  145. A "Content-Base:" or a "Content-Location:" header in the response.
  146.  
  147. For backwards compatability with older HTTP implementations we will
  148. also look for the "Base:" header.
  149.  
  150. =item 3.
  151.  
  152. The URI used to request this response. This might not be the original
  153. URI that was passed to $ua->request() method, because we might have
  154. received some redirect responses first.
  155.  
  156. =back
  157.  
  158. When the LWP protocol modules produce the HTTP::Response object, then
  159. any base URI embedded in the document (step 1) will already have
  160. initialized the "Content-Base:" header. This means that this method
  161. only performs the last 2 steps (the content is not always available
  162. either).
  163.  
  164. =cut
  165.  
  166. sub base
  167. {
  168.     my $self = shift;
  169.     my $base = $self->header('Content-Base')     ||  # used to be HTTP/1.1
  170.                $self->header('Content-Location') ||  # HTTP/1.1
  171.                $self->header('Base');                # HTTP/1.0
  172.     return $HTTP::URI_CLASS->new_abs($base, $self->request->uri);
  173.     # So yes, if $base is undef, the return value is effectively
  174.     # just a copy of $self->request->uri.
  175. }
  176.  
  177.  
  178. =item $r->as_string
  179.  
  180. Returns a textual representation of the response.  Mainly
  181. useful for debugging purposes. It takes no arguments.
  182.  
  183. =cut
  184.  
  185. sub as_string
  186. {
  187.     require HTTP::Status;
  188.     my $self = shift;
  189.     my @result;
  190.     #push(@result, "---- $self ----");
  191.     my $code = $self->code;
  192.     my $status_message = HTTP::Status::status_message($code) || "Unknown code";
  193.     my $message = $self->message || "";
  194.  
  195.     my $status_line = "$code";
  196.     my $proto = $self->protocol;
  197.     $status_line = "$proto $status_line" if $proto;
  198.     $status_line .= " ($status_message)" if $status_message ne $message;
  199.     $status_line .= " $message";
  200.     push(@result, $status_line);
  201.     push(@result, $self->headers_as_string);
  202.     my $content = $self->content;
  203.     if (defined $content) {
  204.     push(@result, $content);
  205.     }
  206.     #push(@result, ("-" x 40));
  207.     join("\n", @result, "");
  208. }
  209.  
  210. =item $r->is_info
  211.  
  212. =item $r->is_success
  213.  
  214. =item $r->is_redirect
  215.  
  216. =item $r->is_error
  217.  
  218. These methods indicate if the response was informational, sucessful, a
  219. redirection, or an error.
  220.  
  221. =cut
  222.  
  223. sub is_info     { HTTP::Status::is_info     (shift->{'_rc'}); }
  224. sub is_success  { HTTP::Status::is_success  (shift->{'_rc'}); }
  225. sub is_redirect { HTTP::Status::is_redirect (shift->{'_rc'}); }
  226. sub is_error    { HTTP::Status::is_error    (shift->{'_rc'}); }
  227.  
  228.  
  229. =item $r->error_as_HTML()
  230.  
  231. Returns a string containing a complete HTML document indicating what
  232. error occurred.  This method should only be called when $r->is_error
  233. is TRUE.
  234.  
  235. =cut
  236.  
  237. sub error_as_HTML
  238. {
  239.     my $self = shift;
  240.     my $title = 'An Error Occurred';
  241.     my $body  = $self->status_line;
  242.     return <<EOM;
  243. <HTML>
  244. <HEAD><TITLE>$title</TITLE></HEAD>
  245. <BODY>
  246. <H1>$title</H1>
  247. $body
  248. </BODY>
  249. </HTML>
  250. EOM
  251. }
  252.  
  253.  
  254. =item $r->current_age
  255.  
  256. Calculates the "current age" of the response as
  257. specified by E<lt>draft-ietf-http-v11-spec-07> section 13.2.3.  The
  258. age of a response is the time since it was sent by the origin server.
  259. The returned value is a number representing the age in seconds.
  260.  
  261. =cut
  262.  
  263. sub current_age
  264. {
  265.     my $self = shift;
  266.     # Implementation of <draft-ietf-http-v11-spec-07> section 13.2.3
  267.     # (age calculations)
  268.     my $response_time = $self->client_date;
  269.     my $date = $self->date;
  270.  
  271.     my $age = 0;
  272.     if ($response_time && $date) {
  273.     $age = $response_time - $date;  # apparent_age
  274.     $age = 0 if $age < 0;
  275.     }
  276.  
  277.     my $age_v = $self->header('Age');
  278.     if ($age_v && $age_v > $age) {
  279.     $age = $age_v;   # corrected_received_age
  280.     }
  281.  
  282.     my $request = $self->request;
  283.     if ($request) {
  284.     my $request_time = $request->date;
  285.     if ($request_time) {
  286.         # Add response_delay to age to get 'corrected_initial_age'
  287.         $age += $response_time - $request_time;
  288.     }
  289.     }
  290.     if ($response_time) {
  291.     $age += time - $response_time;
  292.     }
  293.     return $age;
  294. }
  295.  
  296.  
  297. =item $r->freshness_lifetime
  298.  
  299. Calculates the "freshness lifetime" of the response
  300. as specified by E<lt>draft-ietf-http-v11-spec-07> section 13.2.4.  The
  301. "freshness lifetime" is the length of time between the generation of a
  302. response and its expiration time.  The returned value is a number
  303. representing the freshness lifetime in seconds.
  304.  
  305. If the response does not contain an "Expires" or a "Cache-Control"
  306. header, then this function will apply some simple heuristic based on
  307. 'Last-Modified' to determine a suitable lifetime.
  308.  
  309. =cut
  310.  
  311. sub freshness_lifetime
  312. {
  313.     my $self = shift;
  314.  
  315.     # First look for the Cache-Control: max-age=n header
  316.     my @cc = $self->header('Cache-Control');
  317.     if (@cc) {
  318.     my $cc;
  319.     for $cc (@cc) {
  320.         my $cc_dir;
  321.         for $cc_dir (split(/\s*,\s*/, $cc)) {
  322.         if ($cc_dir =~ /max-age\s*=\s*(\d+)/i) {
  323.             return $1;
  324.         }
  325.         }
  326.     }
  327.     }
  328.  
  329.     # Next possibility is to look at the "Expires" header
  330.     my $date = $self->date || $self->client_date || time;      
  331.     my $expires = $self->expires;
  332.     unless ($expires) {
  333.     # Must apply heuristic expiration
  334.     my $last_modified = $self->last_modified;
  335.     if ($last_modified) {
  336.         my $h_exp = ($date - $last_modified) * 0.10;  # 10% since last-mod
  337.         if ($h_exp < 60) {
  338.         return 60;  # minimum
  339.         } elsif ($h_exp > 24 * 3600) {
  340.         # Should give a warning if more than 24 hours according to
  341.         # <draft-ietf-http-v11-spec-07> section 13.2.4, but I don't
  342.         # know how to do it from this function interface, so I just
  343.         # make this the maximum value.
  344.         return 24 * 3600;
  345.         }
  346.         return $h_exp;
  347.     } else {
  348.         return 3600;  # 1 hour is fallback when all else fails
  349.     }
  350.     }
  351.     return $expires - $date;
  352. }
  353.  
  354.  
  355. =item $r->is_fresh
  356.  
  357. Returns TRUE if the response is fresh, based on the values of
  358. freshness_lifetime() and current_age().  If the response is no longer
  359. fresh, then it has to be refetched or revalidated by the origin
  360. server.
  361.  
  362. =cut
  363.  
  364. sub is_fresh
  365. {
  366.     my $self = shift;
  367.     $self->freshness_lifetime > $self->current_age;
  368. }
  369.  
  370.  
  371. =item $r->fresh_until
  372.  
  373. Returns the time when this entiy is no longer fresh.
  374.  
  375. =cut
  376.  
  377. sub fresh_until
  378. {
  379.     my $self = shift;
  380.     return $self->freshness_lifetime - $self->current_age + time;
  381. }
  382.  
  383. 1;
  384.  
  385. =back 
  386.  
  387. =head1 COPYRIGHT
  388.  
  389. Copyright 1995-2001 Gisle Aas.
  390.  
  391. This library is free software; you can redistribute it and/or
  392. modify it under the same terms as Perl itself.
  393.  
  394. =cut
  395.